# coding=utf-8
from datetime import datetime
from flask import g,current_app
from flask_restful import Resource
from flask_restful.reqparse import RequestParser
from comment.modules.account import Account
from comment.modules.deal_record import DealRecord
from comment.modules.funding_not_matched import Funding_not_matched
from comment.modules.product import Product
from comment.modules.product_rate import Product_rate
from comment.modules.user import User
from comment.ultils.decorators import Login_required
from comment.modules.invest_record import Invest_record
from comment.modules import db
from comment.ultils.gen_trans_id import gen_trans_id
from financial.resorces.transaction.const import DealType
from financial.resorces.transaction.serializer import InvestRecordPaginateSerializer
from dateutil.relativedelta import relativedelta

class Invest_Resource(Resource):

    '''拦截器看用户有没有登录过'''
    # 拦截器他会在LoginOut的所有的视图函数都会在执行视图函数之前，做一下装饰器的拦截
    method_decorators = [Login_required]  # 使用了登录拦截的装饰器

    def get(self):
        '''投资记录资源类'''
        rp = RequestParser()
        rp.add_argument('start') #起始时间
        rp.add_argument('end') #结束时间
        rp.add_argument('invest_type') #投资类型（0是默认值，代表购买中的计划，1表示回款中的计划，2是已完成的计划）
        rp.add_argument('curPage',required=True) #当前页号
        rp.add_argument('per_page',required=True) #每页显示的条数

        args = rp.parse_args()

        start = args.get('start')
        end = args.get('end')
        #判断有没有传值，如果没有，就给1做默认值，有的话。就要传过来的数据，并转化成int类型
        invest_type =0 if args.get('invest_type') == None else int(args.get('invest_type'))
        cur_page = int(args.get('curPage'))
        page_size = int(args.get('per_page'))

        user_id = g.user_id

        #得到一个查询对象
        q = Invest_record.query
        #开始过滤,第一个，根据用户ID过滤
        q = q.filter(Invest_record.pUid == user_id)
        #第二个过滤,根据投资类型过滤
        q = q.filter(Invest_record.pStatus == invest_type)
        #第三个过滤，根据起始时间和结束时间
        if start and end:
            #把数据库datatime的时间转化成date（传两个参数，一个是对象，另外一个是要转化的类型）
            q = q.filter(db.cast(Invest_record.pDate,db.DATE) >= db.cast(start,db.DATE))\
                .filter(db.cast(Invest_record.pDate,db.DATE) <= db.cast(end,db.DATE))#因为前端传的是字符串类型，所以要进行转化
        #分页
        data = q.paginate(cur_page,page_size,error_out=False) #error_out如果没有下一页了就不应该报错

        data = InvestRecordPaginateSerializer(data).to_dict() #字典数据,做分页

        return {
            'msg':'success',
            'data':data
        }

    def post(self):
        '''新增投资或者购买理财'''
        rp = RequestParser()

        rp.add_argument('productId',required=True) #产品ID
        rp.add_argument('pAmount',required=True) #投资金额
        rp.add_argument('period',required=True) #期数
        #rp.add_argument('discount',required=True) #折扣金额

        args = rp.parse_args()

        product_id = args.get('productId')
        p_amount = int(args.get('pAmount'))
        period = int(args.get('period'))
        #discount = args.get('discount')

        user_id = g.user_id
        user = User.query.filter(User.id == user_id).first() #查询当前登录的用户

        #查询产品对象
        product = Product.query.filter(Product.proId == product_id).first()

        #查询产品对应的利率（理财收益年利率），根据产品ID and 理财的期数
        pro_rate = Product_rate.query.filter(Product_rate.productId == product_id)\
            .filter(Product_rate.month == period).first()

        #计算每一期的收益
        #print(pro_rate.incomeRate)
        income = calculate_income(pro_rate.incomeRate,p_amount)

        #修改用户的资金的账户，数据
        try:
            user_account_query = Account.query.filter(Account.userId == user_id)
            user_account = user_account_query.first()
            # 修改之前的账号余额
            before_blance = user_account.balance
            #判断是否可以抵扣金额，每邀请一个人可以得到50的抵扣金额，每次抵扣只能抵扣50元
            cur_discount = 50 if user_account.discount >= 50 else 0 #表示如果里面余额大于等于50的话，只能拿50元的代金券，否则只能减去0
            _p_amount = p_amount - cur_discount #得到真正要支付的金额
            if user_account.balance >= _p_amount: #账户余额足够
                before_bance = user_account.balance
                cur_balance = user_account.balance - _p_amount #得到当前的余额
                discount_balance = user_account.discount - cur_discount #代金券还剩多少
            else: #账户余额不足
                return {
                    'message':'可用余额不足',
                    'code':216
                }

            interestTotal = income * period #当前这一次的投资总共要收的利息

            #修改（推荐用update进行修改，以字典的方式进行修改）
            user_account_query.update({ #键是要修改的键，值就是要修改的值
                #进行重新赋值
                'balance':cur_balance, #帐户可余额
                'inverstmentA':user_account.inverstmentA + p_amount, #已投资总额 = 已投资总额 + 投资金额
                'inverstmentW':user_account.inverstmentW + p_amount, #总计待收本金 = 已投资总额 + 投资金额
                'frozen':user_account.frozen + _p_amount, # 账户总计冻结总额 = 账户总计冻结总额 + 投资金额
                'interestTotal':user_account.interestTotal + interestTotal, #总计待收利息 = 总计待收利息 + 当前这一次的投资总共要收的利息
                'discount':discount_balance #代金券还剩多少
            })

            #新增投资记录
            remark = '使用了50元的代金券' if cur_discount == 50 else '没有使用代金券'
            invest_num = gen_trans_id(DealType.invest.name) #投资的流水号
            p_end_date = datetime.now() + relativedelta(months=period) #投资结束的时间
            invest_days = (p_end_date - datetime.now()).days #精确的投资天数
            invest_record = Invest_record(pProductId=product_id, pUid=user_id, pBeginDate=datetime.now(),
                          pEndDate=p_end_date, pSerialNo=invest_num, pAmount=p_amount,  # pAmount投资金额不用减去代金券的金额
                          pEarnings=pro_rate.incomeRate,
                          pDeadline=period, pMonthInterest=income,
                          pMonthlyExtractInterest=income,
                          pAvailableBalance=user.accountInfo.balance,
                          pFrozenMoney=_p_amount, pProductName=product.productName,
                          pDeadlineAsDay=invest_days, username=user.username,
                          pProspectiveEarnings=interestTotal, pStatus=0, pRemark=remark)
            db.session.add(invest_record)
            db.session.flush()

            #新增待匹配的资金（fNotMatchedMoney待匹配金额，是不减代金券的金额。fFoundingWeight待匹配的权重表示金额比较大，比较重，优先去匹配。matchedStatus匹配状态时未匹配）
            not_matched = Funding_not_matched(fInvestRecordId=invest_record.pId,fNotMatchedMoney=p_amount,fFoundingWeight=1,matchedStatus=0,fCreateDate=datetime.now())

            db.session.add(not_matched)
            #新增交易记录
            deal_num = gen_trans_id(DealType.invest.name) #流水号
            deal_record = DealRecord(aUserId=user_id, pId=invest_record.pId, aReceiveOrPay=1, aTransferSerialNo=deal_num,
                                aTransferStatus=1, aBeforeTradingMoney=before_blance, aAmount=p_amount,
                                aAfterTradingMoney=cur_balance, aDescreption='投资产品购买', aType=DealType.invest.value)
            db.session.add(deal_record)
            db.session.commit()
            return {'msg':'success','data':[]}
        except Exception as e:
            current_app.logger.error(e)
            db.session.rollback() #回滚

def calculate_income(rate,amount): #分别传利率和金额
    #定义计算每一期的收益
    #年利率 / 100 / 12 得每一个月的利率 * 金额 = 每一期的收益
    return  round(rate / 100 / 12 * amount ,2)


if __name__ == '__main__':
    pass





















